﻿using System;
using System.Globalization;

namespace Microsoft.Xna.Framework.Graphics
{
	/// <summary>
	/// Represents a list of 3D vertices to be streamed to the graphics device.
	/// </summary>
	public class VertexBuffer : GraphicsResource
	{
		#region Fields
		internal BufferUsage bufferUsage;
		protected internal int _size;
		internal int vertexCount;
		internal VertexDeclaration vertexDeclaration;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the state of the related BufferUsage enumeration.
		/// </summary>
		public BufferUsage BufferUsage
		{
			get { return bufferUsage; }
		}

		/// <summary>
		/// Gets the number of vertices.
		/// </summary>
		public int VertexCount
		{
			get { return vertexCount; }
		}

		/// <summary>
		/// Defines per-vertex data in a buffer.
		/// </summary>
		public VertexDeclaration VertexDeclaration
		{
			get { return vertexDeclaration; }
		}
		#endregion

		#region Constructor
		/// <summary>
		/// Creates an instance of this object.
		/// </summary>
		/// <param name="graphicsDevice">The graphics device.</param>
		/// <param name="vertexDeclaration">The vertex declaration, which describes per-vertex data.</param>
		/// <param name="vertexCount">The number of vertices.</param>
		/// <param name="usage">Behavior options; it is good practice for this to match the createOptions parameter in the GraphicsDevice constructor.</param>
		public VertexBuffer(GraphicsDevice graphicsDevice, VertexDeclaration vertexDeclaration, int vertexCount, BufferUsage usage)
		{
			if (vertexDeclaration == null)
			{
				throw new ArgumentNullException("vertexDeclaration", FrameworkResources.NullNotAllowed);
			}
			if (vertexCount <= 0)
			{
				throw new ArgumentOutOfRangeException("vertexCount", FrameworkResources.ResourcesMustBeGreaterThanZeroSize);
			}

			base.GraphicsDevice = graphicsDevice;
			//! TODO: implement remainder

			int num = vertexDeclaration._vertexStride * vertexCount;
			if (num > 0x3ffffff)
			{
				throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, FrameworkResources.ProfileTooBig, GraphicsProfile.Reach, typeof(VertexBuffer).Name, 0x3ffffff));
			}

			this._size = num;
			this.vertexCount = vertexCount;
			this.vertexDeclaration = vertexDeclaration;
		}

		/// <summary>
		/// Creates an instance of this object.
		/// </summary>
		/// <param name="graphicsDevice">The graphics device.</param>
		/// <param name="vertexType">The data type.</param>
		/// <param name="vertexCount">The number of vertices.</param>
		/// <param name="usage">Behavior options; it is good practice for this to match the createOptions parameter in the GraphicsDevice constructor.</param>
		public VertexBuffer(GraphicsDevice graphicsDevice, Type vertexType, int vertexCount, BufferUsage usage)
		{
			//! TODO: implement
			if (vertexCount <= 0)
			{
				throw new ArgumentOutOfRangeException("vertexCount", FrameworkResources.ResourcesMustBeGreaterThanZeroSize);
			}
			base.GraphicsDevice = graphicsDevice;
			//! TODO: implement remainder
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Gets a copy of the vertex buffer data.
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="data">Array of data.</param>
		public void GetData<T>(T[] data) where T : struct
		{
			int length;
			if (data != null)
			{
				length = data.Length;
			}
			else
			{
				length = 0;
			}
			this.GetData<T>(0, data, 0, length, 0);
		}

		public void GetData<T>(T[] data, int startIndex, int elementCount) where T : struct
		{
			this.GetData<T>(0, data, startIndex, elementCount, 0);
		}

		public void GetData<T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
		{
		}

		public void SetData<T>(T[] data) where T : struct
		{
		}

		public void SetData<T>(T[] data, int startIndex, int elementCount) where T : struct
		{
		}

		public void SetData<T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct
		{
		}
		#endregion
	}
}
